
var ctx;
var canvas;

function new_draw_string() {
	return {
		str: ' ',
		clr: 'white',
		pnt: '12',
		x: 0,
		y: 0,
		align: 'left'
	}
}

function canvas_clear() {
	ctx.clearRect(0, 0, canvas.width, canvas.height);
	ctx.fillStyle = "rgb(0, 0, 0)";
	ctx.fillRect(0, 0, canvas.width, canvas.height);
}

function canvas_share() {
	document.location ='mailto:?body=' + escape(
		'<b><img src="' + 
		canvas.toDataURL('image/png') +
		'" /></b>'
	);
}

function canvas_save() {
	window.open(canvas.toDataURL('image/png'));
}

function canvas_init() {
	canvas = document.getElementById('canvas');
	ctx = canvas.getContext('2d');
	canvas_clear();
}

function new_draw_line() {
	return {
		clr: 'white',
		thick: '1.0',
		xa: 0,
		ya: 0,
		xb: 0,
		yb: 0
	}
}

function draw_line(l) {
	// l is an object with the following properties
	// l.clr line color
	// l.thick line thickness
	// l.xa point a
	// l.yb "
	// l.xa point b
	// l.yb "

	ctx.save();
	ctx.strokeStyle = l.clr;
	ctx.lineCap = "round";
	ctx.lineWidth = l.thick;
	ctx.beginPath();

	var xa = parseFloat('' + l.xa);
	var ya = parseFloat('' + l.ya);
	var xb = parseFloat('' + l.xb);
	var yb = parseFloat('' + l.yb);
	var thick = parseFloat('' + l.thick);

	ctx.moveTo(xa, ya);
	ctx.lineTo(xb, yb);
	ctx.stroke();

	ctx.restore();
}

function rainbow_numbers(r) {
	//r is between 0 and 1
	//we want a rainbow color

	var c = (r - Math.floor(r)) * 6;
	var d = Math.floor(c);
	//d %= 6; // should never happen
	var v = c - d;
	if (1 == d % 2) {
		v = 1 - v;
	}

	//alert (r + ":" + c + ":" + v);

	v *= 255;
	v = Math.floor(v);
	//v %= 256; // should never happen...

	var o = [];

	if (0 == d) {
		//red to yellow
		o = [255, v, 0];
	} else if (1 == d) {
		//yellow to green
		o = [v, 255, 0];
	} else if (2 == d) {
		//green to cyan
		o = [0, 255, v];
	} else if (3 == d) {
		//cyan to blue
		o = [0, v, 255];
	} else if (4 == d) {
		//blue to magenta
		o = [v, 0, 255];
	} else if (5 == d) {
		//magenta to red
		o = [255, 0, v];
	}

	//alert(r + ":" + o)
	return o;
}

function rainbow_color(r) {
	var o = rainbow_numbers(r);
	return "rgb(" + o.join(",") + ")";
}

function new_draw_rainbow_line() {
	return {
		clra: '0.0',
		clrb: '1.0',
		steps: '32',
		thick: '1.0',
		xa: 0,
		ya: 0,
		xb: 0,
		yb: 0
	}
}

function step_rainbow_line(l) {
	var s = new_draw_rainbow_line();
	s.steps = Math.abs(Math.floor(parseFloat("" + l.steps)));
	if (null == s.steps || 0 == s.steps) {
		s.steps = 1;
	}

	s.clra = parseFloat("" + l.clra);
	s.clrb = parseFloat("" + l.clrb);
	s.thick = parseFloat("" + l.thick);
	s.xa = parseFloat("" + l.xa);
	s.ya = parseFloat("" + l.ya);
	s.xb = parseFloat("" + l.xb);
	s.yb = parseFloat("" + l.yb);
	s.dx = s.xb - s.xa;
	s.dx /= s.steps;
	s.dy = s.yb - s.ya;
	s.dy /= s.steps;
	s.dclr = s.clrb - s.clra;
	s.dclr /= s.steps;
	s.prev = 0;
	s.step = 1/s.steps;

	return s;
}

function draw_rainbow_line(l) {
	var s = step_rainbow_line(l);
	for (var i = 1; i <= s.steps; ++i) {
		draw_rainbow_line_step(s, i); 
	}
}

function animate_rainbow_line(l, c, f, delay) {
	//f: abort callback
	//c: completed callback
	
	var t = delay;
	if (null == t) { t = 10; }
	var s = step_rainbow_line(l);
	if (null != f) { if (! f()) { return; } }
	animate_rainbow_line_step(s, 1, c, f, t);
}

function animate_rainbow_line_step(s, i, c, f, delay) {
	//f: abort callback
	//c: completed callback
	var t = delay;
	if (null == t) { t = 10; }
	if (null != f) { if (! f()) { return; } }
	if (i > s.steps) {
		if (null != c) { c(); }
		return;
	} else {
		draw_rainbow_line_step(s, i); 
		if (i < s.steps) { 
			draw_rainbow_line_next_step(s, i);
		}
		var g = function() {
			animate_rainbow_line_step(s, i + 1, c, f, t);
		}
		setTimeout(g, t);
	}
}

function draw_rainbow_line_next_step(s, i) {
	var step = (i + 1)/s.steps;
	var xb = s.xa + s.dx;
	var yb = s.ya + s.dy;
	var clr = s.clra + s.dclr;
	var l = new_draw_line();

	l.clr = 'white'; //rainbow_color(s.clra + .5);
	l.xa = s.xa;
	l.xb = xb;
	l.ya = s.ya;
	l.yb = yb;
	l.thick = s.thick;

	//s.clra = clr;
	//s.xa = xb;
	//s.ya = yb;

	draw_line(l);
}

function draw_rainbow_line_step(s, i) {
	var step = i/s.steps;
	var xb = s.xa + s.dx;
	var yb = s.ya + s.dy;
	var clr = s.clra + s.dclr;
	var l = new_draw_line();

	l.clr = rainbow_color(s.clra);
	l.xa = s.xa;
	l.xb = xb;
	l.ya = s.ya;
	l.yb = yb;
	l.thick = s.thick;

	s.clra = clr;
	s.xa = xb;
	s.ya = yb;

	draw_line(l);
}

function new_draw_dot() {
	return {
		x: "0.0",
		y: "0.0",
		r: "1.0",
		clr: "white"
	};
}

function draw_dot(d) {
	var x = parseFloat("" + d.x);
	var y = parseFloat("" + d.y);
	var r = parseFloat("" + d.r);
	var c = d.clr;

	ctx.save();
	ctx.fillStyle = d.clr;

	ctx.beginPath();
	ctx.arc(x, y, r, 0, 2 * Math.PI, false);
	ctx.fill();

	ctx.restore();
}

function new_draw_dot_circle() {
	return {
		r: "0.0",
		dr: "1.0",
		x: "0.0",
		y: "0.0",
		count: "1",
		clr: "white"
	};
}

function draw_dot_circle_dot(c, t) {
	// x is radius * cos theta
	// y is radius * sin theta
	// but we're starting with theta at pi/2 (90)

	var theta = (t * 2 * Math.PI) - (Math.PI / 2);

	var d = new_draw_dot();
	d.r = c.dr;
	d.clr = c.clr;
	d.x = c.x + c.r * Math.cos(theta);
	d.y = c.y + c.r * Math.sin(theta);

	draw_dot(d);
	return { x: d.x, y: d.y };
}

function draw_dot_circle(c) {
	var d = new_draw_dot_circle();
	var a = new Array();
	d.x = parseFloat(c.x);
	d.y = parseFloat(c.y);
	d.r = parseFloat(c.r);
	d.dr = parseFloat(c.dr);
	d.count = parseInt(c.count);
	d.clr = c.clr;
	for (var i = 0; i < d.count; ++i) {
		a.push(draw_dot_circle_dot(d, i/d.count));
	}
	return a;
}
